/*
 * io.c - 
 */

#include <io.h>
#include <utils.h>

/**************/
/** Screen  ***/
/**************/

#define NUM_COLUMNS 80
#define NUM_ROWS    25

Byte x, y=15;

/* Read a byte from 'port' */
Byte inb (unsigned short port)
{
  Byte v;

  __asm__ __volatile__ ("inb %w1,%0":"=a" (v):"Nd" (port));
  return v;
}

void clear(int row, int column) {
  Word ws = (Word) (' ' & 0x00FF) | 0x200;
  DWord screen = 0xb8000 + (row * NUM_COLUMNS) * 2;
  while (column < NUM_COLUMNS) {
    asm("movw %0, (%1)" : : "r"(ws), "r"(screen + column * 2));
    column++;
  }
}

void scroll() {
	int i;
	DWord current, above;
	for (i = 1; i < NUM_ROWS; i++) {
		current = 0xb8000 + (i * NUM_COLUMNS) * 2;
		above = 0xb8000 + ((i - 1) * NUM_COLUMNS) * 2;
		copy_data((void *)current, (void *)above, NUM_COLUMNS * 2);
	}
	clear(NUM_ROWS - 1, 0);
}

void printc(char c)
{
  Word ch = (Word) (c & 0x00FF) | 0x0200;
  DWord screen = 0xb8000 + (y * NUM_COLUMNS + x) * 2;
   __asm__ __volatile__ ( "movb %0, %%al; outb $0xe9" ::"a"(c));
  if (c == '\n') {
	clear(y, x);
    x = 0;
    if (++y >= NUM_ROWS)
      y = NUM_ROWS - 1;
      scroll();
  }
  else {
    asm("movw %0, (%1)" : : "r"(ch), "r"(screen));
    if (++x >= NUM_COLUMNS)
    {
      x = 0;
      if (++y >= NUM_ROWS)
        y = NUM_ROWS - 1;
        scroll();
    }
  }
}

void printc_xy(int x, int y, char c)
{
  Word ch = (Word) (c & 0x00FF) | 0x0200;
  DWord screen = 0xb8000 + (y * NUM_COLUMNS + x) * 2;
  asm("movw %0, (%1)" : : "r"(ch), "r"(screen));
}

void printk(char *string)
{
  int i;
  for (i = 0; string[i]; i++)
    printc(string[i]);
}

void printk_xy(int x, int y, char *string) {
  int i;
  for (i = 0; string[i]; i++)
    printc_xy(x+i, y, string[i]);
}
